package com.punai.config.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import com.punai.config.constants.PnConfigConstants;
import com.punai.config.service.ConfigFeatureElementService;
import com.punai.config.service.ConfigGenerateCodeService;
import com.punai.config.sqlitedao.ConfigEngineerClassLinkFeatureRepository;
import com.punai.config.sqlitedao.ConfigFeatureElementRepository;
import com.punai.config.sqlitedomain.ConfigEngineerLinkElement;
import com.punai.config.sqlitedomain.ConfigFeatureElement;
import com.punai.config.sqlitedomain.vo.ConfigFeatureElementVo;
import io.netty.util.internal.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import java.text.ParseException;
import java.util.*;

@Service
public class ConfigFeatureElementServiceImpl implements ConfigFeatureElementService {

    @Autowired
    private ConfigFeatureElementRepository configFeatureElementRepository;
    @Autowired
    private ConfigEngineerClassLinkFeatureRepository configEngineerClassLinkFeatureRepository;
    @Autowired
    private ConfigGenerateCodeService configGenerateCodeService;

    @Override
    public Page<ConfigFeatureElement> selectList(ConfigFeatureElementVo vo) throws ParseException {
        Page<ConfigFeatureElement> findPage;
        Integer pageSize = vo.getPageSize();
        Integer pageNumber = vo.getPageNumber();
        PageRequest pageRequest =  PageRequest.of(pageNumber, pageSize);
        Map<String,Object> paramMap = new HashMap<>();
        String formatId = vo.getFormatId();
        String engineerClassId = vo.getEngineerClassId();
        String engineerClassCode = vo.getEngineerClassCode();
        if (StrUtil.isNotEmpty(formatId)) {
            paramMap.put("formatCategoryId",formatId);
        } else if (StrUtil.isNotBlank(engineerClassId)) {
            paramMap.put("engineerClassId",engineerClassId);
            paramMap.put("engineerClassCode",engineerClassCode);
        }
        paramMap.put("featureType",vo.getFeatureType());
        if(paramMap.containsKey("engineerClassId")||paramMap.containsKey("engineerClassCode")){
            findPage = configFeatureElementRepository.findPageByengineerClass(paramMap, pageRequest);
        }else{
            findPage = configFeatureElementRepository.findPageByformat(paramMap, pageRequest);
        }
        return findPage;
    }

    @Override
    public int add(ConfigFeatureElement configFeatureElement) throws ParseException {
        ConfigFeatureElement save=null;
        ConfigFeatureElement findByCode = configFeatureElementRepository.findByCode(configFeatureElement.getCode());
        if(findByCode!=null){
            if(StrUtil.isBlank(configFeatureElement.getId())){
                return 0;
            }
            if(!configFeatureElement.getId().equals(findByCode.getId())){
                return 0;
            }
        }
        if(StrUtil.isNotBlank(configFeatureElement.getId())){
            //update
            save=configFeatureElementRepository.update(configFeatureElement);
        }else{
            save=configFeatureElementRepository.save(configFeatureElement);
            ConfigEngineerLinkElement formatLinkFeature = new ConfigEngineerLinkElement();
            formatLinkFeature.setFeatureId(save.getId());
            formatLinkFeature.setClassId(configFeatureElement.getClassId());
            configEngineerClassLinkFeatureRepository.save(formatLinkFeature);
        }
        return 1;
    }

    @Override
    public ConfigFeatureElement getInfo(String id) throws ParseException {
        return configFeatureElementRepository.findOne(id);
    }

    @Override
    public int deleteInfo(String id) {
        return configFeatureElementRepository.delete(id);
    }

    @Override
    public boolean checkCalculateCaliberType(String classId, String calculateCaliberType) throws ParseException {
        Map<String,Object> paramMap = new HashMap<>();
        paramMap.put("engineerClassId",classId);
        paramMap.put("calculateCaliberType",calculateCaliberType);
        List<ConfigFeatureElement> allOfEng = configFeatureElementRepository.findAllOfEng(paramMap);
        return CollUtil.isEmpty(allOfEng);
    }

    @Override
    public int copyOtherClassNode(String classIds, String elementIds) throws ParseException {
        List<String> classIdList = StrUtil.split(classIds, ",");
        List<String> elementIdList = StrUtil.split(elementIds, ",");
        Map<String, String> parentids= new HashMap<>();
        for (String id : elementIdList) {
            ConfigFeatureElement findOne = configFeatureElementRepository.findOne(id);
            for (String ClassId : classIdList) {
                findOne.setId(null);
                findOne.setCode(configGenerateCodeService.getNextCode(PnConfigConstants.CODE_TYPE.ELE_CODE));
                findOne.setPid(null);
                //根据PID是否为空，复制父类
                if(findOne.getParent()!=null){
                    if(parentids.containsKey(findOne.getParent().getId())) {
                        // 用新的父id
                        findOne.setPid(parentids.get(findOne.getParent().getId()));
                    }else{
                        String oldId=findOne.getParent().getId();
                        ConfigFeatureElement save = saveParentOfMethodCopyToEngineerClass(findOne.getParent(), ClassId);
                        findOne.setPid(save.getId());
                        parentids.put(oldId,save.getId());
                    }
                }
                ConfigFeatureElement save = this.saveToEngineerClass(findOne, ClassId);
                parentids.put(id,save.getId());
                if(save==null){
                    return 0;
                }
            }
        }
        return 1;
    }

    @Override
    public boolean moveToFormatForm(String moveId, String nextId, String prevId) throws ParseException {
        if(StringUtil.isNullOrEmpty(moveId)){
            return false;
        }
        if(StringUtil.isNullOrEmpty(nextId)){
            if(StringUtil.isNullOrEmpty(prevId)){
                return false;
            }else{
                //上移
                ConfigEngineerLinkElement findByFeature = configEngineerClassLinkFeatureRepository.findByFeature(moveId);
                ConfigEngineerLinkElement findByFeature1 = configEngineerClassLinkFeatureRepository.findByFeature(prevId);
                Integer sorting = findByFeature.getSorting();
                Integer sorting1 = findByFeature1.getSorting();
                findByFeature.setSorting(sorting1);
                findByFeature1.setSorting(sorting);
                configEngineerClassLinkFeatureRepository.update(findByFeature);
                configEngineerClassLinkFeatureRepository.update(findByFeature1);
            }

        }else{
            //下移
            ConfigEngineerLinkElement findByFeature = configEngineerClassLinkFeatureRepository.findByFeature(moveId);
            ConfigEngineerLinkElement findByFeature1 = configEngineerClassLinkFeatureRepository.findByFeature(nextId);
            Integer sorting = findByFeature.getSorting();
            Integer sorting1 = findByFeature1.getSorting();
            findByFeature.setSorting(sorting1);
            findByFeature1.setSorting(sorting);
            configEngineerClassLinkFeatureRepository.update(findByFeature);
            configEngineerClassLinkFeatureRepository.update(findByFeature1);
        }
        return true;
    }

    private ConfigFeatureElement saveParentOfMethodCopyToEngineerClass(ConfigFeatureElement thisOne,String categoryId) throws NumberFormatException, ParseException{
        if(thisOne.getParent()==null){
            // 说明是顶层
            thisOne.setId(null);
            thisOne.setCode(configGenerateCodeService.getNextCode(PnConfigConstants.CODE_TYPE.ELE_CODE));
            ConfigFeatureElement save = this.saveToEngineerClass(thisOne, categoryId);
            return save;
        }
        ConfigFeatureElement parent = saveParentOfMethodCopyToEngineerClass(thisOne.getParent(),categoryId);
        thisOne.setId(null);
        thisOne.setCode(configGenerateCodeService.getNextCode(PnConfigConstants.CODE_TYPE.ELE_CODE));
        thisOne.setPid(parent.getId());
        ConfigFeatureElement save = this.saveToEngineerClass(thisOne, categoryId);
        return save;
    }


    public ConfigFeatureElement saveToEngineerClass(ConfigFeatureElement newFeatureElement,String classId)
            throws NumberFormatException, ParseException {
        ConfigFeatureElement save=null;
        ConfigFeatureElement findByCode = configFeatureElementRepository.findByCode(newFeatureElement.getCode());
        if(findByCode!=null){
            if(StringUtil.isNullOrEmpty(newFeatureElement.getId())){
                return null;
            }
            if(!newFeatureElement.getId().equals(findByCode.getId())){
                return null;
            }
        }
        if(StrUtil.isNotBlank(newFeatureElement.getId())){
            //update
            save=configFeatureElementRepository.update(newFeatureElement);
        }else{
            save=configFeatureElementRepository.save(newFeatureElement);
            ConfigEngineerLinkElement formatLinkFeature = new ConfigEngineerLinkElement();
            formatLinkFeature.setFeatureId(save.getId());
            formatLinkFeature.setClassId(classId);
            configEngineerClassLinkFeatureRepository.save(formatLinkFeature);
        }
        return save;
    }


    private void saveChildrenOfMethodCopyToEngineerClass(List<ConfigFeatureElement> parentChildren,ConfigFeatureElement parent,String formatid) throws NumberFormatException, ParseException{
        for (ConfigFeatureElement findOne : parentChildren) {
            findOne.setId(null);
            // findOne.setCode(GenerateCodeUtil.generateCode(BSConstants.CODE_TYPE.ELE_CODE));
            findOne.setPid(parent.getId());
            ConfigFeatureElement save = this.saveToEngineerClass(findOne, formatid);
            saveChildrenOfMethodCopyToEngineerClass(findOne.getChildren(), save, formatid);
        }
    }

}
